﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using DevComponents.AdvTree;
using DevComponents.DotNetBar;

namespace PolePosition.v3.Desktop.Utility
{
    public partial class AssetAssociations : Office2007Form
    {
        private int countColumns;

        public AssetAssociations()
        {
            InitializeComponent();
        }

        private void buttonReadPasteData_Click(object sender, EventArgs e)
        {
            ShowPanel(panelPage2);

            try
            {
                bool nodesOk = true;
                advTree1.Nodes.Clear();
                textAssets.Text = textAssets.Text.Trim();
                
                if (textAssets.Lines.Length > 0)
                    countColumns = textAssets.Lines[0].Split((char)Keys.Tab).Length;

                foreach (var assetLine in textAssets.Lines)
                {
                    bool nodeOk;
                    var values = assetLine.Split((char) Keys.Tab);

                    if (values.Length > 6 || values.Length < 2)
                        throw new Exception("Between two or six columns were expected.");

                    var assetNode = CreateNode(values, out nodeOk);

                    if (!nodeOk)
                        nodesOk = false;

                    advTree1.Nodes.Add(assetNode);
                }

                if (!nodesOk)
                    throw new Exception("There were problems while parsing the data. Please, check the pasted data, all values should be numbers or empty for null values.");

                buttonUpdate.Enabled = true;
            }
            catch (Exception exc)
            {
                buttonUpdate.Enabled = false;
                MessageBoxEx.Show(exc.Message, "Critical Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private Node CreateNode(string[] assetIds, out bool nodeOk)
        {
            var assetNode = new Node();
            nodeOk = true;

            //If the column exists, gets the value else empty
            assetNode.Text = countColumns > 0 ? assetIds[0] : string.Empty;
            assetNode.Tag = true;
            assetNode.Cells.Add(new Cell(countColumns > 1 ? assetIds[1] : string.Empty));
            assetNode.Cells.Add(new Cell(countColumns > 2 ? assetIds[2] : string.Empty));
            assetNode.Cells.Add(new Cell(countColumns > 3 ? assetIds[3] : string.Empty));
            assetNode.Cells.Add(new Cell(countColumns > 4 ? assetIds[4] : string.Empty));
            assetNode.Cells.Add(new Cell(countColumns > 5 ? assetIds[5] : string.Empty));

            nodeOk &= MarkIfCellIsValid(assetIds, assetNode.Cells[0], 0);
            nodeOk &= MarkIfCellIsValid(assetIds, assetNode.Cells[1], 1);
            nodeOk &= MarkIfCellIsValid(assetIds, assetNode.Cells[2], 2);
            nodeOk &= MarkIfCellIsValid(assetIds, assetNode.Cells[3], 3);
            nodeOk &= MarkIfCellIsValid(assetIds, assetNode.Cells[4], 4);
            nodeOk &= MarkIfCellIsValid(assetIds, assetNode.Cells[5], 5);

            return assetNode;
        }



        private void buttonUpdate_Click(object sender, EventArgs e)
        {
            try 
            {
                Cursor = Cursors.WaitCursor;
                CheckInvalidIds();
                UpdateAssetParents();

                MessageBoxEx.Show("Asset associations have been updated succesfully!", "PPI", MessageBoxButtons.OK, MessageBoxIcon.Information);
                Close();
            }
            catch(Exception exc)
            {
                buttonUpdate.Enabled = false;
                MessageBoxEx.Show(exc.Message, "PPI", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            finally
            {
                Cursor = Cursors.Arrow;
            }
        }

        private void CheckInvalidIds()
        {
            var nodesToUpdate = new List<int>();

            foreach (Node node in advTree1.Nodes)
            {
                if (!node.Text.Trim().Equals(string.Empty))
                    nodesToUpdate.Add(int.Parse(node.Text));

                if (!node.Cells[1].Text.Equals(string.Empty))
                    nodesToUpdate.Add(int.Parse(node.Cells[1].Text));

                if (!node.Cells[2].Text.Equals(string.Empty))
                    nodesToUpdate.Add(int.Parse(node.Cells[2].Text));

                if (!node.Cells[3].Text.Equals(string.Empty))
                    nodesToUpdate.Add(int.Parse(node.Cells[3].Text));

                if (!node.Cells[4].Text.Equals(string.Empty))
                    nodesToUpdate.Add(int.Parse(node.Cells[4].Text));

                if (!node.Cells[5].Text.Equals(string.Empty))
                    nodesToUpdate.Add(int.Parse(node.Cells[5].Text));
            }

            int[] notValidIds = ServiceProxy.UtilityService.DistributionAssetsValidateIds(Program.LoginResult.Utility.UtilityId.Value, nodesToUpdate.ToArray());
            var notValidIdsList = new List<int>(notValidIds);
            bool invalidNodes = false;

            foreach (Node node in advTree1.Nodes)
            {
                if (!node.Text.Trim().Equals(string.Empty) && notValidIdsList.Contains(int.Parse(node.Text)))
                    MarkCellAsInvalid(node.Cells[0]);

                if (!node.Cells[1].Text.Trim().Equals(string.Empty) && notValidIdsList.Contains(int.Parse(node.Cells[1].Text)))
                    MarkCellAsInvalid(node.Cells[1]);

                if (!node.Cells[2].Text.Trim().Equals(string.Empty) && notValidIdsList.Contains(int.Parse(node.Cells[2].Text)))
                    MarkCellAsInvalid(node.Cells[2]);

                if (!node.Cells[3].Text.Trim().Equals(string.Empty) && notValidIdsList.Contains(int.Parse(node.Cells[3].Text)))
                    MarkCellAsInvalid(node.Cells[3]);

                if (!node.Cells[4].Text.Trim().Equals(string.Empty) && notValidIdsList.Contains(int.Parse(node.Cells[4].Text)))
                    MarkCellAsInvalid(node.Cells[4]);

                if (!node.Cells[5].Text.Trim().Equals(string.Empty) && notValidIdsList.Contains(int.Parse(node.Cells[5].Text)))
                    MarkCellAsInvalid(node.Cells[5]);

                if (!IsNodeValid(node))
                    invalidNodes = true;
            }

            advTree1.Refresh();

            if (invalidNodes)
            {
                advTree1.Focus();
                throw new Exception("Some Ids don't exist.");
            }
        }

        private void UpdateAssetParents()
        {
            var xmlWriterSettings = new XmlWriterSettings();
            xmlWriterSettings.Encoding = new UTF8Encoding(false);
            xmlWriterSettings.ConformanceLevel = ConformanceLevel.Document;
            xmlWriterSettings.Indent = true;

            var memoryStream = new MemoryStream();
            var xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings);
            xmlWriter.WriteStartElement("assets");

            foreach (Node node in advTree1.Nodes)
            {
                if (((bool)node.Tag)) //Valid node
                {
                    xmlWriter.WriteStartElement("asset");

                    xmlWriter.WriteAttributeString("id", node.Text);
                    xmlWriter.WriteElementString("parentAssetFk1", node.Cells[1].Text);
                    xmlWriter.WriteElementString("parentAssetFk2", node.Cells[2].Text);
                    xmlWriter.WriteElementString("parentAssetFk3", node.Cells[3].Text);
                    xmlWriter.WriteElementString("parentAssetFk4", node.Cells[4].Text);
                    xmlWriter.WriteElementString("parentAssetFk5", node.Cells[5].Text);

                    xmlWriter.WriteEndElement();
                }
            }

            xmlWriter.WriteEndElement();
            xmlWriter.Flush();

            string xmlString = Encoding.UTF8.GetString(memoryStream.ToArray());

            //Send xmlString to update the parent assets.
            ServiceProxy.UtilityService.DistributionAssetsUpdateParents(xmlString);
        }

        private static void MarkCellAsInvalid(Cell cell)
        {
            cell.StyleNormal = new ElementStyle { BackColor = Color.Pink };
            cell.Parent.Tag = false;
            
        }

        private static bool IsParsedCellValid(string parsedCell)
        {
            int idValue;
            
            if (!parsedCell.Trim().Equals(string.Empty) && !int.TryParse(parsedCell, out idValue))
                return false;

            return true;
        }

        private static bool IsNodeValid(Node node)
        {
            if (node.Tag != null)
                return (bool) node.Tag;

            return false;
        }

        private void buttonBack_Click(object sender, EventArgs e)
        {
            ShowPanel(panelPage1);
        }

        private void ShowPanel (Panel panel)
        {
            panelPage2.Visible = false;
            panelPage1.Visible = false;

            panel.Visible = true;
        }

        private bool MarkIfCellIsValid(string[] assetIds, Cell cell, int index)
        {
            if (countColumns > index && !IsParsedCellValid(assetIds[index]))
            {
                MarkCellAsInvalid(cell);
                return false;
            }

            return true;
        }
    }
}
